<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>D3.js Parallel Coordinates Plot</title>  
    <script src="https://d3js.org/d3.v6.min.js"></script>  
    <style>  
        .axis line {  
            stroke: #000;  
            shape-rendering: crispEdges;  
        }  
        .axis text {  
            font: 12px sans-serif;  
        }  
        .line {  
            fill: none;  
            stroke: #69b3a2;  
            stroke-width: 1.5px;  
        }  
    </style>  
</head>  
<body>  
    <div id="parallel-plot"></div>  
    <script>  
        // 设置图表尺寸和边距  
        const margin = { top: 20, right: 10, bottom: 30, left: 10 };  
        const width = 800 - margin.left - margin.right;  
        const height = 400 - margin.top - margin.bottom;  
  
        // 创建SVG容器  
        const svg = d3.select("#parallel-plot").append("svg")  
            .attr("width", width + margin.left + margin.right)  
            .attr("height", height + margin.top + margin.bottom)  
          .append("g")  
            .attr("transform", `translate(${margin.left},${margin.top})`);  
  
        // 示例数据  
        const data = [  
            { 'Name': 'A', 'Math': 85, 'Science': 90, 'English': 78 },  
            { 'Name': 'B', 'Math': 70, 'Science': 80, 'English': 85 },  
            { 'Name': 'C', 'Math': 95, 'Science': 75, 'English': 80 },  
            // ... 可以添加更多数据点  
        ];  
  
        // 提取维度（列名）  
        const dimensions = Object.keys(data[0]).slice(1); // 排除 'Name' 列  
  
        // 计算每个维度的范围  
        const ranges = dimensions.map(d => d3.extent(data.map(row => row[d])));  
  
        // 设置X轴的比例尺（线性比例尺用于每个维度）  
        const x = {};  
        dimensions.forEach((d, i) => {  
            x[d] = d3.scaleLinear()  
                .domain(ranges[i])  
                .range([i * (width / (dimensions.length - 1)), (i + 1) * (width / (dimensions.length - 1))]);  
        });  
  
        // 添加轴线  
        dimensions.forEach((d, i) => {  
            svg.append("g")  
                .attr("class", "axis")  
                .attr("transform", `translate(${i * (width / (dimensions.length - 1))},0)`)  
                .call(d3.axisTop(x[d]).ticks(4).tickSize(-height));  
        });  
  
        // 添加垂直线以连接轴线（可选，用于更好地可视化轴之间的分隔）  
        svg.selectAll(".vline")  
            .data(d3.range(1, dimensions.length))  
          .enter().append("line")  
            .attr("class", "vline")  
            .attr("x1", d => d * (width / (dimensions.length - 1)))  
            .attr("x2", d => d * (width / (dimensions.length - 1)))  
            .attr("y1", 0)  
            .attr("y2", height)  
            .style("stroke", "#ccc");  
  
        // 绘制线（每条线代表一个数据点）  
        svg.selectAll(".line")  
            .data(data)  
          .enter().append("path")  
            .attr("class", "line")  
            .attr("d", d => {  
                return dimensions.map((dim, i) => {  
                    const xPos = x[dim](d[dim]);  
                    return i === 0 ? `M${xPos},${height}` : `L${xPos},${height}`;  
                }).join('');  
            })  
            .attr("stroke-dasharray", (d, i) => i === 0 ? "3,3" : "") // 为第一条线添加虚线样式以区分（可选）  
            .style("fill", "none");  
  
        // 由于D3默认不支持路径的渐变填充，如果需要为路径添加颜色渐变，则需要额外的代码（在此示例中未包含）  
  
    </script>  
</body>  
</html>